package net.xiaoboli.mgp;

import lombok.SneakyThrows;
import org.apache.commons.lang3.StringUtils;
import org.mybatis.generator.api.ConnectionFactory;
import org.mybatis.generator.api.IntrospectedTable;
import org.mybatis.generator.api.PluginAdapter;
import org.mybatis.generator.config.JDBCConnectionConfiguration;
import org.mybatis.generator.internal.JDBCConnectionFactory;
import org.mybatis.generator.internal.ObjectFactory;
import org.mybatis.generator.logging.Log;
import org.mybatis.generator.logging.LogFactory;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.Instant;
import java.util.Date;
import java.util.List;

/**
 * permission import  plugin
 */
public class PermissionPlugin extends PluginAdapter {

    private String c, r, u, d;
    private String permissionTable;
    private Log log;

    @Override
    public boolean validate(List<String> list) {
        c = properties.getProperty("C");
        r = properties.getProperty("R");
        u = properties.getProperty("U");
        d = properties.getProperty("D");
        permissionTable = properties.getProperty("permissionTable");

        if (c == null) c = "Add";
        if (r == null) r = "View";
        if (u == null) u = "Update";
        if (d == null) d = "Delete";

        if (permissionTable == null || permissionTable.trim().length() == 0)
            permissionTable = "sys_permission";

        return true;
    }


    @SneakyThrows
    @Override
    public void initialized(IntrospectedTable introspectedTable) {
        this.log = LogFactory.getLog(this.getClass());

        String noPermission = introspectedTable.getTableConfigurationProperty("permission");
        if ("no".equals(noPermission)) {
            log.warn(introspectedTable.getFullyQualifiedTableNameAtRuntime() + " permission skip create because permission configured to no");
            return;
        }

        try {
            this.addPermission(introspectedTable);
        } catch (Exception e) {
            e.printStackTrace();
            throw e;
        }
    }

    private Connection getConnection() throws SQLException {
        Object connectionFactory;
        JDBCConnectionConfiguration jdbcConnectionConfiguration = context.getJdbcConnectionConfiguration();
        if (jdbcConnectionConfiguration != null) {
            connectionFactory = new JDBCConnectionFactory(jdbcConnectionConfiguration);
        } else {
            connectionFactory = ObjectFactory.createConnectionFactory(context);
        }
        return ((ConnectionFactory) connectionFactory).getConnection();
    }

    private int queryLastOrderNumber(int pid) throws SQLException {
        int lastOrderNum = 0;

        try (Connection connection = this.getConnection()) {
            String sql = "";
            PreparedStatement preparedStatement;
            //从主路径判断是否已被添加过
            sql = "SELECT max(order_num) FROM " + permissionTable + " WHERE pid=" + pid;
            preparedStatement = connection.prepareStatement(sql);
            try(ResultSet rs = preparedStatement.executeQuery()) {
                if (rs.next()) {
                    lastOrderNum = rs.getInt(1);
                }
            }
        }

        return lastOrderNum;
    }

    private void addPermission(IntrospectedTable introspectedTable) throws SQLException {String recordType = introspectedTable.getBaseRecordType();
        String modelName = recordType.substring(recordType.lastIndexOf(".") + 1);
        String remarks = introspectedTable.getRemarks();
        if (StringUtils.isEmpty(remarks)) {
            remarks = modelName;
        }

        //
        Date now = new Date();
        Instant d2020 = Instant.parse("2021-01-01T00:00:00.00Z");
        try (Connection connection = this.getConnection()) {

//        id 				varchar(50)	 NOT NULL 		COMMENT '权限标识'
//                ,name 				varchar(50)	 DEFAULT NULL 		COMMENT '权限名称'
//                ,pid 				varchar(50)	 DEFAULT NULL 		COMMENT '父级ID'
//                ,order_num 			int			 DEFAULT 0 			COMMENT '排序'
//                ,is_disabled		int			 DEFAULT 0			COMMENT '是否禁用,0:正常,1:禁用'

            String id = "", name = "", pid = "";
            int orderNum = queryLastOrderNumber(0);
            orderNum ++;

            String sql = "";
            PreparedStatement preparedStatement;

            //权限列表
//            List<String[]> plist = new ArrayList<>();
//            plist.add(new String[]{String.format(c, modelName),modelName + ".Create"});
//            plist.add(new String[]{String.format(d, modelName),modelName + ".Delete"});
//            plist.add(new String[]{String.format(u, modelName),modelName + ".Update"});
//            plist.add(new String[]{String.format(r, modelName),modelName + ".Read"});

            //删除旧
//            sql = "DELETE FROM "+permissionTable+" WHERE id=? or pid=?";
//            preparedStatement = connection.prepareStatement(sql);
//            preparedStatement.setString(1, modelName);
//            preparedStatement.setString(2, modelName);
//            preparedStatement.execute();

            //添加新
            sql = "";
            sql += "INSERT INTO " + permissionTable + " ";
            sql += "(id,name,pid,order_num,is_disabled)";
            sql += "VALUES";
            sql += "(?, ?   ,?  ,?        ,0)";


            //System.out.println(String.format("Add permission %s [C,R,U,D]", modelName));

            if (!this.have(modelName, connection)) {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, modelName);
                preparedStatement.setString(2, remarks);
                preparedStatement.setString(3, "-");
                preparedStatement.setInt(4, orderNum);
                preparedStatement.execute();
                System.out.println(String.format("Add permission %s", modelName));
            }

            //CRUD

            //C
            if (!this.have(modelName + ".Create", connection)) {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, modelName + ".Create");
                preparedStatement.setString(2, String.format(c, modelName));
                preparedStatement.setString(3, modelName);
                preparedStatement.setInt(4, 1);
                preparedStatement.execute();
                System.out.println(String.format("Add permission %s.Create", modelName));
            }
            //D
            if (!this.have(modelName + ".Delete", connection)) {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, modelName + ".Delete");
                preparedStatement.setString(2, String.format(d, modelName));
                preparedStatement.setString(3, modelName);
                preparedStatement.setInt(4, 2);
                preparedStatement.execute();
                System.out.println(String.format("Add permission %s.Delete", modelName));
            }
            //U
            if (!this.have(modelName + ".Update", connection)) {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, modelName + ".Update");
                preparedStatement.setString(2, String.format(u, modelName));
                preparedStatement.setString(3, modelName);
                preparedStatement.setInt(4, 3);
                preparedStatement.execute();
                System.out.println(String.format("Add permission %s.Update", modelName));
            }
            //R
            if (!have(modelName + ".Read", connection)) {
                preparedStatement = connection.prepareStatement(sql);
                preparedStatement.setString(1, modelName + ".Read");
                preparedStatement.setString(2, String.format(r, modelName));
                preparedStatement.setString(3, modelName);
                preparedStatement.setInt(4, 4);
                preparedStatement.execute();
                System.out.println(String.format("Add permission %s.Read", modelName));
            }

        }


    }

    private boolean have(String id, Connection connection) throws SQLException {
        //查找现有
        String sql = "SELECT id FROM " + permissionTable + " WHERE id=?";
        boolean have = false;

        try (PreparedStatement preparedStatement = connection.prepareStatement(sql)) {
            preparedStatement.setString(1, id);
            try (ResultSet resultSet = preparedStatement.executeQuery()) {
                while (resultSet.next()) {
                    //String id = resultSet.getString(1);
                    have = true;
                }
            }
        }
        return have;
    }

}
